/****************************************************************************
 * Elisa 1.0                                                                *
 *--------------------------------------------------------------------------*
 * Author: Laurent Granvilliers, Vincent Sorin                              *
 * Copyright (c) 2004 Laboratoire d'Informatique de Nantes Atlantique       *
 *--------------------------------------------------------------------------*
 * Elisa is distributed WITHOUT ANY WARRANTY. Read the associated           *
 * COPYRIGHT file for more details.                                         *
 *--------------------------------------------------------------------------*
 * elisa_compound_reduction.h                                               *
 ****************************************************************************/

/**
 * @file elisa_compound_reduction.h
 * @brief Classes for compound reduction.
 */


#ifndef _ELISA_COMPOUND_REDUCTION_H
#define _ELISA_COMPOUND_REDUCTION_H

#include "elisa_defs.h"
#include "elisa_reduction.h"
#include "elisa_time.h"

NAMESPACE_ELISA

/**
 * @ingroup Reduction
 * @class CompoundReduction
 */
class CompoundReduction : public Reduction
{
public:
	/**
 	 * Constructor
 	 */
	CompoundReduction ()
	{
	}

	/**
 	 * Destructor
 	 * @post all reduction added in this reduction are deleted
 	 */
	virtual ~CompoundReduction ()
	{
		/*
 		   VecReduction::const_iterator it;
 		   for (it=_elemReduction.begin(); it!=_elemReduction.end(); ++it)
 		   {
 		   delete (*it);
 		   }
 		 */
	}

	/**
 	 * Insertion of a reduction in the compound reduction
 	 * @param o the reduction to add
 	 */
	void addReduction(Reduction *o)
	{
		if (o != 0) {
			_elemReduction.push_back(ReductionPtr(o));
			// THIS must be called if o becomes active
			o->addDependentReduction(this);
		}
	}

	/**
 	 * Insertion of a set of reductions in the compound reduction
 	 * @param s the Set of reduction to add
 	 */
	void addReduction(SetReduction & s)
	{
		SetReduction::const_iterator it;
		for (it = s.begin(); it != s.end(); ++it) {
			addReduction(*it);
		}
	}

	/**
 	 * To active all reductions linked to this reduction
 	 * it calls the initActive method for all the reductions of *this
 	 */
	virtual void initActive()
	{
		Reduction::initActive();
		VecReduction::const_iterator it;
		for (it = _elemReduction.begin(); it != _elemReduction.end(); ++it) {
			(*it)->initActive();
		}
	}

	/**
 	 * To asleep all reductions linked to this reduction
 	 * it calls the initInactive method for all the reductions of *this
 	 */
	virtual void initInactive()
	{
		Reduction::initInactive();
		VecReduction::const_iterator it;
		for (it = _elemReduction.begin(); it != _elemReduction.end(); ++it) {
			(*it)->initInactive();
		}
	}

	const VecReduction *getElemReduction() const
	{
		return &_elemReduction;
	}

	virtual void print(std::ostream & os, std::string indent, VecConstraints *v) const
	{
		os << "[\n";
		char c = 'a';
		VecReduction::const_iterator it;
		for (it = _elemReduction.begin(); it != _elemReduction.end(); it++) {
			os << "(" << c << ") : ";

			(*it)->print(os, indent + "      ", v);

			os << "\n";

			c++;
			if (c > 'z')
				c = 'A';
		}
		os << "]";
	}


protected:
	/// Vector of reductions to be applied by the compound reduction
	VecReduction _elemReduction;
};

END_NAMESPACE_ELISA

#endif
